#include <io.h>
#include <iostream>
#include <string>
#include <sstream>

#if defined( _MSC_VER )
	#include <crtdbg.h>
	#define WIN32_LEAN_AND_MEAN
	#include <windows.h>
	_CrtMemState startMemState;
	_CrtMemState endMemState;
#endif

using namespace std;

bool dirExists(const std::string& dirName_in);

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	string srcDir; 
	string destDir;

	// parse the command line (dodgy code - my C++ needs work)

	string item;
	stringstream ss(lpCmdLine);
	ss >> item;
	if (item[0] == '"')
	{
		if (item[item.length() - 1]=='"') 
		{
			srcDir = (item.substr(1, item.length()-2));
		} 
		else 
		{
			string restOfItem;
			getline(ss, restOfItem, '"');
			srcDir = (item.substr(1) + restOfItem);
		}
		srcDir = string(lpCmdLine).substr(srcDir.length() + 2);
	}
	else
	{
		srcDir = item;
		destDir = string(lpCmdLine).substr(srcDir.length());
	}

	// trim leading white space 
	while (destDir[0]==' ') 
	{
		destDir = destDir.substr(1, destDir.length() - 1);
	}

	// remove outer quotes if needeed
	if (destDir[0]=='"') 
	{
		destDir = destDir.substr(1, destDir.length() - 2);
	} 

	// todo wait until running Java process is dead
	// Currently this just sleeps, but it should really poll the process or something
	Sleep(2000);

	string srcAppDir = srcDir + "\\app";
	string srcJreDir = srcDir + "\\runtime\\jre";
	string destAppDir = destDir + "\\app";
	string destJreDir = destDir + "\\runtime\\jre";

	//MessageBox(NULL, TEXT(srcDir.c_str()), TEXT("Info"), MB_OK);
	//MessageBox(NULL, TEXT(destDir.c_str()), TEXT("Info"), MB_OK);

	// todo delete old files

	// move each new file in the 'app' dir across
	//MessageBox(NULL, TEXT( string("Src APP Dir: " + srcAppDir).c_str() ), TEXT("Info"), MB_OK);
    if(dirExists(srcAppDir.c_str()))
	{
		WIN32_FIND_DATA data;
		HANDLE hFile = FindFirstFile((srcAppDir + "\\*").c_str(), &data);
		if  (hFile != INVALID_HANDLE_VALUE)
		{
			do 
			{
				string fileName = string(data.cFileName);
				if (fileName.compare(".") != 0 && fileName.compare("..") != 0)
				{
					string pathToFile = srcAppDir + "\\" + fileName;
					string destFile = destAppDir + "\\" + fileName;
					//MessageBox(NULL, TEXT(pathToFile.c_str()), TEXT("Info"), MB_OK);
					DeleteFile(destFile.c_str());
					MoveFile(pathToFile.c_str(), destFile.c_str());
				}
			}
			while(FindNextFile(hFile, &data) != 0 || GetLastError() != ERROR_NO_MORE_FILES);
		}
	}

	// replace 'jre' dir if it exists in the new bundle
    if(dirExists(srcJreDir.data()))
	{
		if(dirExists(destJreDir.data()))
		{
			// delete old jre dir as we will be replacing it
			RemoveDirectory(destJreDir.data());
		}
		MoveFile(srcJreDir.data(), destJreDir.data());
	}


	// launch the new app 

	STARTUPINFO         siStartupInfo;
    PROCESS_INFORMATION piProcessInfo;
    memset(&siStartupInfo, 0, sizeof(siStartupInfo));
    memset(&piProcessInfo, 0, sizeof(piProcessInfo));
    siStartupInfo.cb = sizeof(siStartupInfo);

	// todo work out 'exe' name, currently hard coded
	string command = destDir + "\\EnsembleWithZenUpdate.exe";

	//MessageBox(NULL, TEXT(string("Launching: " + command).data()), TEXT("Launch Failed"), MB_OK);
    
	if(CreateProcess(command.c_str(),		// Application name
					 (LPSTR)"",  // Application arguments
                     0,
                     0,
                     FALSE,
                     CREATE_DEFAULT_ERROR_MODE,
                     0,
                     0,                              // Working directory
                     &siStartupInfo,
                     &piProcessInfo) == FALSE)
	{
		 // Could not start application -> call 'GetLastError()'
		MessageBox(NULL, TEXT("There was an error while launching the application"), TEXT("Launch Failed"), MB_OK);
		return FALSE;
	}

	return TRUE;
}

bool dirExists(const std::string& dirName_in)
{
  DWORD ftyp = GetFileAttributesA(dirName_in.c_str());
  if (ftyp == INVALID_FILE_ATTRIBUTES)
    return false;  //something is wrong with your path!

  if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
    return true;   // this is a directory!

  return false;    // this is not a directory!
}